package cn.cpf.tool.doc.pdf;

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.LayoutStyle;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.filechooser.FileNameExtensionFilter;

/**
 * <b>Description : </b>
 *
 * @author CPF
 * Date: 2020/5/7 10:05
 */
public class MainJFrame extends JFrame {
    private static final String TITLE_PROGRAM = "PDFBOOKMARK-Exchanger (Import/Export Bookmark)";

    private JButton btnBKMLoad;

    private JButton btnBKMSave;

    private JButton btnClear;

    private JButton btnOpen;

    private JButton btnSave;

    private JLabel jLabel1;

    private JLabel jLabel2;

    private JLabel jLabelVersion;

    private JLabel jLabelWeb;

    private JScrollPane jScrollPane1;

    private JTextField jTexBkmPage;

    private JTextArea jTextBookmark;

    private JTextField jTextPDFPage;

    enum RFile {
        PDFOPEN(0),
        PDFSAVE(1),
        TXTOPEN(2),
        TXTSAVE(3);

        private int value;

        private static String[] files = new String[4];

        private static final int NUM = 2;

        static {

        }

        RFile(int value) {
            this.value = value;
        }

        private static String getFile(int v) {
            String strFile = ".";
            if (null == files[v] || files[v].isEmpty()) {
                int a = v / 2, b = (v % 2 == 0) ? 1 : 0;
                int[] c = new int[3];
                c[0] = 2 * a + b;
                a = (a == 0) ? 1 : 0;
                c[1] = 2 * a;
                c[2] = 2 * a + 1;
                for (int i = 0; i < c.length; i++) {
                    int u = c[i];
                    if (null != files[u] && !files[u].isEmpty()) {
                        strFile = files[u];
                        break;
                    }
                }
            } else {
                strFile = files[v];
            }
            return strFile;
        }

        String getFile() {
            return getFile(this.value);
        }

        void setFile(String strFile) {
            files[this.value] = strFile;
        }
    }

    public MainJFrame() {
        initComponents();
        init();
    }

    public void init() {
        setNumericOnly(this.jTextPDFPage);
        setNumericOnly(this.jTexBkmPage);
        setTitle("PDFBOOKMARK-Exchanger (Import/Export Bookmark)");
    }

    public void checkBasePage(String str) {
        if (str.isEmpty())
            return;
        int basePage = PDFBookmarkManager.findBasePageFromString(str);
        if (-1 != basePage) {
            this.jTexBkmPage.setText("1");
            this.jTextPDFPage.setText(String.valueOf(basePage));
        }
    }

    public static void setNumericOnly(JTextField jText) {
        jText.addKeyListener(new KeyAdapter() {
            public void keyTyped(KeyEvent e) {
                char c = e.getKeyChar();
                if (!Character.isDigit(c) || c == '\b' || c == '')
                    e.consume();
            }
        });
    }

    private static String FileChooser(Component parent, String strDesc, String strSuffix, boolean bOpen, String strTitle) {
        return FileChooser(parent, strDesc, strSuffix, bOpen, strTitle, ".");
    }

    private static String FileChooser(Component parent, String strDesc, String strSuffix, boolean bOpen, String strTitle, String curPath) {
        String strFile = "";
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setCurrentDirectory(new File(curPath));
        fileChooser.setAcceptAllFileFilterUsed(false);
        FileNameExtensionFilter filter = new FileNameExtensionFilter(strDesc, new String[] { strSuffix });
        fileChooser.setFileFilter(filter);
        int returnVal = 0;
        if (strTitle.isEmpty()) {
            if (bOpen) {
                returnVal = fileChooser.showOpenDialog(parent);
            } else {
                returnVal = fileChooser.showSaveDialog(parent);
            }
        } else {
            fileChooser.setDialogTitle(strTitle);
            if (bOpen) {
                returnVal = fileChooser.showDialog(parent, "Open");
            } else {
                returnVal = fileChooser.showDialog(parent, "Save");
            }
        }
        if (returnVal == 0) {
            strFile = fileChooser.getSelectedFile().getPath();
            int index = strFile.lastIndexOf("." + strSuffix);
            if (-1 == index)
                strFile = strFile + "." + strSuffix;
        }
        return strFile;
    }

    private void initComponents() {
        this.btnOpen = new JButton();
        this.btnSave = new JButton();
        this.jScrollPane1 = new JScrollPane();
        this.jTextBookmark = new JTextArea();
        this.btnBKMSave = new JButton();
        this.btnBKMLoad = new JButton();
        this.btnClear = new JButton();
        this.jLabel1 = new JLabel();
        this.jTexBkmPage = new JTextField();
        this.jLabel2 = new JLabel();
        this.jTextPDFPage = new JTextField();
        this.jLabelWeb = new JLabel();
        this.jLabelVersion = new JLabel();
        setDefaultCloseOperation(3);
        addWindowListener(new WindowAdapter() {
            public void windowOpened(WindowEvent evt) {
                MainJFrame.this.formWindowOpened(evt);
            }
        });
        this.btnOpen.setText("Open ...");
        this.btnOpen.setToolTipText("Open from TXT file");
        this.btnOpen.addActionListener(MainJFrame.this::btnOpenActionPerformed);
        this.btnSave.setText("Store ...");
        this.btnSave.setToolTipText("Store to TXT file");
        this.btnSave.addActionListener(MainJFrame.this::btnSaveActionPerformed);
        this.jTextBookmark.setColumns(20);
        this.jTextBookmark.setRows(5);
        this.jTextBookmark.setTabSize(4);
        this.jScrollPane1.setViewportView(this.jTextBookmark);
        this.btnBKMSave.setText("Save...");
        this.btnBKMSave.setToolTipText("Save Bookmark to PDF file");
        this.btnBKMSave.addActionListener(MainJFrame.this::btnBKMSaveActionPerformed);
        this.btnBKMLoad.setText("Load...");
        this.btnBKMLoad.setToolTipText("Load Bookmak from PDF file");
        this.btnBKMLoad.addActionListener(MainJFrame.this::btnBKMLoadActionPerformed);
        this.btnClear.setText("Clear");
        this.btnClear.setToolTipText("Clear Content.");
        this.btnClear.addActionListener(MainJFrame.this::btnClearActionPerformed);
        this.jLabel1.setText("Bookmark PageNum:");
        this.jTexBkmPage.setText("1");
        this.jTexBkmPage.setToolTipText("Bookmark Page Number.");
        this.jLabel2.setText("Real PDF PageNum: ");
        this.jTextPDFPage.setText("1");
        this.jTextPDFPage.setToolTipText("Real Page Number in PDF file.");
        this.jLabelWeb.setText("http://blog.csdn.net/yinqingwang");
        this.jLabelVersion.setText("PDFBookmark-Exchanger(ver 1.0.2)");
        GroupLayout layout = new GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(layout
                .createParallelGroup(GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                                .addComponent(this.jScrollPane1)
                                .addGroup(layout.createSequentialGroup()
                                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                                                .addGroup(GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                                        .addComponent(this.jLabel1)
                                                        .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED))
                                                .addGroup(layout.createSequentialGroup()
                                                        .addComponent(this.btnBKMLoad)
                                                        .addGap(37, 37, 37)))
                                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING, false)
                                                .addComponent(this.btnBKMSave, -1, -1, 32767)
                                                .addComponent(this.jTexBkmPage))
                                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, -1, 32767)
                                        .addComponent(this.jLabel2)
                                        .addGap(18, 18, 18)
                                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING, false)
                                                .addGroup(layout.createSequentialGroup()
                                                        .addComponent(this.btnOpen)
                                                        .addGap(18, 18, 18))
                                                .addGroup(layout.createSequentialGroup()
                                                        .addComponent(this.jTextPDFPage)
                                                        .addGap(19, 19, 19)))
                                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING, false)
                                                .addComponent(this.btnClear, -1, -1, 32767)
                                                .addComponent(this.btnSave, -1, -1, 32767)))
                                .addGroup(layout.createSequentialGroup()
                                        .addComponent(this.jLabelWeb, -2, 435, -2)
                                        .addGap(18, 18, 32767)
                                        .addComponent(this.jLabelVersion, -2, 210, -2)))
                        .addContainerGap()));
        layout.setVerticalGroup(layout
                .createParallelGroup(GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                                .addComponent(this.jLabel1)
                                .addComponent(this.jTexBkmPage, -2, -1, -2)
                                .addComponent(this.jLabel2)
                                .addComponent(this.jTextPDFPage, -2, -1, -2)
                                .addComponent(this.btnClear))
                        .addGap(5, 5, 5)
                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                                .addComponent(this.btnOpen)
                                .addComponent(this.btnSave)
                                .addComponent(this.btnBKMSave)
                                .addComponent(this.btnBKMLoad))
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(this.jScrollPane1, -2, 681, -2)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, -1, 32767)
                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                                .addComponent(this.jLabelWeb)
                                .addComponent(this.jLabelVersion))));
        this.jLabelWeb.getAccessibleContext().setAccessibleName("http://haha");
        pack();
    }

    private void btnOpenActionPerformed(ActionEvent evt) {
        try {
            RFile rFile = RFile.TXTOPEN;
            String strFile = FileChooser(getContentPane(), "TXT file (UTF-8 encode)(*.txt)", "txt", true, "Open Text File", rFile.getFile());
            if (strFile.isEmpty())
                return;
            Scanner inFile = new Scanner(new File(strFile), "UTF-8");
            this.jTextBookmark.setText("");
            while (inFile.hasNext()) {
                String line = inFile.nextLine();
                this.jTextBookmark.append(line + System.getProperty("line.separator"));
            }
            checkBasePage(this.jTextBookmark.getText());
            rFile.setFile(strFile);
        } catch (Exception exception) {}
    }

    private void btnSaveActionPerformed(ActionEvent evt) {
        PrintWriter out = null;
        try {
            RFile rFile = RFile.TXTSAVE;
            String strFile = FileChooser(getContentPane(), "TXT file (UTF-8 encode)(*.txt)", "txt", false, "Save Text File", rFile.getFile());
            if (strFile.isEmpty())
                return;
            out = new PrintWriter(new File(strFile), "UTF-8");
            out.println(this.jTextBookmark.getText());
            JOptionPane.showMessageDialog(null, "Save finished! \n\n\t" + strFile);
            rFile.setFile(strFile);
        } catch (Exception exception) {

        } finally {
            out.close();
        }
    }

    private void btnBKMLoadActionPerformed(ActionEvent evt) {
        try {
            RFile rFile = RFile.PDFOPEN;
            String strFile = FileChooser(getContentPane(), "PDF file (*.pdf)", "pdf", true, "Load PDF File", rFile.getFile());
            fileDispose(strFile);
            rFile.setFile(strFile);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }



    private boolean fileDispose(String strFile) {
        if (strFile.isEmpty())
            return true;
        int basePage = PDFBookmarkManager.getBasePage(this.jTexBkmPage.getText(), this.jTextPDFPage.getText());
        String str = PDFBookmarkManager.getBookmarkStringFromPDF(strFile, basePage);
        if (str.isEmpty()) {
            JOptionPane.showMessageDialog(null, "No bookmark found! \n\n\t" + strFile);
            return true;
        }
        this.jTextBookmark.setText(str);
        return false;
    }




    private void btnBKMSaveActionPerformed(ActionEvent evt) {
        try {
            String bkmPage = this.jTexBkmPage.getText();
            String pdfPage = this.jTextPDFPage.getText();
            int basePage = PDFBookmarkManager.getBasePage(bkmPage, pdfPage);
            RFile rFile = RFile.PDFSAVE;
            String strFile = FileChooser(getContentPane(), "PDF file (*.pdf)", "pdf", false, "Save PDF File", rFile.getFile());
            if (strFile.isEmpty())
                return;
            String str = this.jTextBookmark.getText();
            if (str.isEmpty())
                throw new Exception("Content of Bookmark is empty!");
            PDFBookmarkManager.saveBookmarkStringToPDF(strFile, str, basePage);
            JOptionPane.showMessageDialog(null, "Save PDF finished!");
            rFile.setFile(strFile);
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(null, ex.getMessage());
        }
    }

    private void btnClearActionPerformed(ActionEvent evt) {
        this.jTextBookmark.setText("");
        this.jTexBkmPage.setText("1");
        this.jTextPDFPage.setText("1");
    }

    private void formWindowOpened(WindowEvent evt) {
        this.jTextBookmark.requestFocus();
    }

    public static void main(String[] args) {
        try {
            for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(MainJFrame.class.getName()).log(Level.SEVERE, (String)null, ex);
        } catch (InstantiationException ex) {
            Logger.getLogger(MainJFrame.class.getName()).log(Level.SEVERE, (String)null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(MainJFrame.class.getName()).log(Level.SEVERE, (String)null, ex);
        } catch (UnsupportedLookAndFeelException ex) {
            Logger.getLogger(MainJFrame.class.getName()).log(Level.SEVERE, (String)null, ex);
        }
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                MainJFrame frame = new MainJFrame();
                frame.setVisible(true);
                frame.setResizable(false);
            }
        });
    }
}
